
package ChatGUI;



import ChatController.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;

/**
 * La classe GUI hérite de trois classes filles : ConversationWindow, ConnectWindow et DisconnectWindow
 * Elle correspond à l'interface visible par l'utilisateur du chat
 * @author Marion et Nicolas
 */

public class ChatGUI implements FromUser, ToUser, Observer{

    //Trois fenetres de conversation possible : fenetre initale, fenetre de conversation et fenetre de deconnexion
    private static DisconnectWindow dw;  
    private static ConnectWindow cw;
    private static ChatWindow chw;
    // Cette liste nous permet de memoriser toutes les fenêtre ouvertes, pour que lors de la deconection elle puisse se fermer
    private ArrayList chList = new ArrayList <ChatWindow>();
    
    
       /**
     * Attribut servant à mémoriser le login d'une fenêtre à l'autre
     */
    public static String logLocal;    
      /**
     * Attribut boolean qui sert pour la méthode update
     */
    public static boolean display =true;    
        /**
     * Attribut qui contient le login d'un remote user
     */
    protected String logRemote;
    private static Model modele;
    /**
     * Liaison avec le ChatController
     */
    protected static ChatController controller;
    
    /**
     * Liste des users
     */
    protected static HashMap userWindow;
 
/**
 * Constructeur de la classe ChatGUI
 * @param control
 * @param m 
 */

    public ChatGUI(ChatController control, Model m){
        ChatGUI.userWindow = new HashMap <String,ChatWindow> ();
        ChatGUI.controller=control;
        ChatGUI.modele=m;
        modele.addObserver(this);
        dw = new DisconnectWindow("",this);      // 3 états possibles : normal,erreur,fermeturefenêtre
    }  


    /**
     * Méthode appelée par la classe ConnectWindow
     */
    @Override
    public void performDisconnect(){
        try {
            performSendAll();
        } catch (Exception e) {
            System.out.println("Erreur dans l'envoie du Bye de deconnexion (performDisconnect du GUI)");
        }
    }
    

    /**
     * Méthode appelée par les classes ConnectWindow et DisconnectWindow
     * Envoi d'un BYE en broadcast
     */
    @Override
    public void performSendAll(){
        try {
           controller.sendToAll("", "", false, true);     // false=>hello and true=>bye
        } catch (Exception e) {
            System.out.println("Erreur dans le performSendAll du ChatGUI !!");
        }
    }
    
    
    /**
     * Envoi d'un HELLO en broadcast
     * @param username 
     */
    @Override
    public void performSendAll(String username){
        try {
           ChatGUI.controller.sendToAll(username, "", true, false);                
        } catch (Exception e) {
            System.out.println("Erreur dans le performSendAll du DisconnectWindow !! (hello envoye via l'alternative)");
        }
    }
     
    /**
     * Envoi d'un HELLO en broadcast
     * @param username 
     */
     public void performConnect(String username){
        try {
           performSendAll(username);          
        } catch (Exception e) {
            System.out.println("Erreur dans l'envoi du Hello de connexion");
        }
    }

     /**
      * Envoi d'un message text en broadcast
      * @param mess 
      */
    @Override
    public void performSendTextAll(String mess){
        try {
            controller.sendToAll("", mess, false,false);        
        } catch (Exception e) {
            System.out.println("Erreur dans l'envoi de message texteToAll du ChatGUI");
        }
    }
    
    /**
     * Méthode appelée par la classe ChatWindow
     * @param message
     * @param dest 
     */
    @Override
    public void performSendMessage(String message,String dest){
           System.out.println("remote"+dest);
           ChatGUI.controller.sendToNI(dest,message);
    }
        
      /**
     * Méthode perrmettant d'obtenir une addresse à partir d'un login
     * Cette méthode est utilisée par le ChatController
     * @param login
     * @return 
     */
   private Object getWindowFromLogin(String login){
       return userWindow.get(login);
   }
   
       /**
    * Méthode permettant d'ouvrir une nouvelle fenêtre de connexion
    */ 
    @Override
   public void connection(){
         cw = new ConnectWindow("",logLocal,this);
    }
    
      /**
    * Méthode permettant d'ouvrir une nouvelle fenêtre de conversation
    * On l'appelle pour démarrer une nouvelle conversation avec un utilisateur
    * @param remote
    */
    @Override
    public void conversation(String remote){
        chw = new ChatWindow(remote,this);
    }
    

    /**
     * Méthode qui permet de dire au controller que l'on souhaite ouvrir une conversation 
     * @param log 
     */
    @Override
    public void startingConversation(String log){
            controller.newConversation(log);
    }
    
    
    
/**
 * Méthode de mise à jour des fenêtres sur l'arrivée de différents évènements
 * @param o
 * @param arg 
 */
    @Override
    public void update(Observable o, Object arg) {        
        if (arg instanceof TypeOfNotify){
            if (display) {
                
                // Ajout/Suppression dans la liste
                TypeOfNotify type = (TypeOfNotify)arg;
                String connected = type.getConnected();   
                String disconnected = type.getDisconnected();
                String logUser = type.getUserIN();      // Login de l'user qui se co (si qqn se co)
                String logUser2= type.getUserOUT();     // Login de l'user qui se deco (si qqn se deco)
                String remoteUser = type.getOpenWindow();
                String messageIN = type.getMessageIN();
                String loginAssociated = type.getLoginAssociated();
                String messageOUT= type.getMessageOUT();

                if(connected !=null){
                    System.out.println("fenetre connection avant :"+ cw);
                    connection();
                    System.out.println("fenetre connection apres :"+ cw);
                }
                else if (disconnected != null){
                    dw = new DisconnectWindow("",this);
                    cw.emptyingList();
                    display=false; 
                    
                    // Parcours de la liste des fenetres instancie pour les fermer lors de la deconnection
                    for (int i=0;i<chList.size();i++){
                        chw=(ChatWindow)chList.get(i);
                        chw.dispose();
                    }
                    userWindow.clear();
                 }


                System.out.println("etat : "+connected+ " logUser :"+logUser+"; logUser2 : "+logUser2+"; remoteUser(mess) : " +remoteUser+ "; messageIN : "+messageIN+"; loginAssocie : "+loginAssociated+"; messageOUT : "+messageOUT);

                if (logUser != null) {
                    System.out.println("update du GUI2.5");
                    System.out.println(cw);
                    cw.addInList(logUser);
                    System.out.println("update du GUI3");
                    ConnectWindow.listUser.updateUI();
                }

                else if (logUser2 != null){
                    ChatGUI.cw.removeFromList(logUser2);
                }

                // Ouverture fenêtre conversation

                else if(remoteUser != null){                            // Quand on click YES du asker !!
                    if (userWindow.containsKey(remoteUser)){            // Si fenêtre n'existe pas dejà
                        chw = (ChatWindow)getWindowFromLogin(remoteUser);
                        System.out.println("Fenêtre de chat deja ouverte");
                    }
                    else {
                        conversation(remoteUser);              // true => On affiche la fenêtre
                        userWindow.put(remoteUser, chw);            // On associe un user à une fenêtre
                        chList.add(chw);
                    }
                }

                // Reception d'un message

                else if (messageIN != null && loginAssociated != null){
                    System.out.println("reception d'un message..");
                    cw.afficherMessage(loginAssociated,messageIN);

                    if (userWindow.containsKey(loginAssociated)){               // Si fenêtre existe déjà
                        chw = (ChatWindow)getWindowFromLogin(loginAssociated);  // alors on recupère l'instance de chw qu'on veut
                        chw.afficheMessage(messageIN);                          // on l'affiche dans cette fenêtre là
                        System.out.println("message reçu correctement");
                    }
                    else {
                        conversation(loginAssociated);          // On ouvre une fenêtre dés la reception d'un message
                        userWindow.put(loginAssociated, chw);
                        chw.afficheMessage(messageIN);
                        chList.add(chw);
                        System.out.println("Ouverture de fenêtre (reception d'un message)");
                    }
                }
            }
        }
    }
    
}
